﻿using System;
using System.Security.Cryptography;
using CryptSharp.Utility;

namespace StartReading.Security.Cryptography
{
    public static class Password
    {
        private static readonly int DefaultSaltLengthBytes = (int) Math.Pow( 2,  8 );
        private static readonly int DefaultCpuCost         = (int) Math.Pow( 2, 17 );
        private static readonly int DefaultMemoryCost      = (int) Math.Pow( 2,  5 );
        private static readonly int DefaultParallelization = (int) Math.Pow( 2,  0 );
        private static readonly int DefaultHashLengthBytes = (int) Math.Pow( 2,  6 );

        /// <summary>
        ///     Generates random salt
        /// </summary>
        public static byte[] RandomSalt
        {
            get
            {
                var saltBytes = new byte[ Password.DefaultSaltLengthBytes ];
                var randomNumberGenerator = new RNGCryptoServiceProvider();
                randomNumberGenerator.GetBytes( saltBytes );
                return saltBytes;
            }
        }

        /// <summary>
        ///     Hashes password with SCrypt algorithm
        /// </summary>
        /// <param name="password">
        ///     Password or passphrase bytes used for login or authentication
        /// </param>
        /// <param name="salt">
        ///     Random salt bytes which will be added to password before hashing is calculated
        /// </param>
        /// <returns>Hashed value</returns>
        public static byte[] Hash( byte[] password, byte[] salt )
        {
            var output = new byte[ Password.DefaultHashLengthBytes ];
            SCrypt.ComputeKey( password, salt, DefaultCpuCost, DefaultMemoryCost, DefaultParallelization, null, output );
            return output;
        }
    }
}
